#include "GLEffectProperty.h"

#include <Rz/Graphics/Render/IRenderDevice.h>
#include <Rz/Graphics/Render/Libraries/OpenGL/GLEffect.h>
#include <Rz/Graphics/Render/Libraries/OpenGL/GLTexture2D.h>
#include "GL.h"

namespace Rz { namespace Graphics { namespace Render { namespace Libraries { namespace OpenGL {

GLEffectProperty::GLEffectProperty(IEffect* effect)
{
	this->SetEffect(effect);
}

GLEffectProperty::GLEffectProperty(IEffect* effect, const String& name)
{
	this->SetEffect(effect);
	Init(name);
}

GLEffectProperty::~GLEffectProperty()
{

}

void GLEffectProperty::Init(const String& name)
{
	this->SetPropertyName(name);
	this->GetEffect()->Bind();

	_location = static_cast<GLint>(this->GetEffect()->FindUniformIndex(name));
}
		
void GLEffectProperty::SetBool(bool value) 
{
	if (_location != NoPosition)
	{
		GL::Uniform1i(_location, value ? true : false); 
	}
}

void GLEffectProperty::SetInt32(s32 value) 
{ 
	if (_location != NoPosition)
	{
		GL::Uniform1i(_location, value);
	}
}

void GLEffectProperty::SetFloat(f32 value) 	
{ 
	if (_location != NoPosition)
	{
		GL::Uniform1f(_location, value); 
	}
}

void GLEffectProperty::SetVector2(const Math::Vector2& value)
{ 
	if (_location != NoPosition)
	{
		GL::Uniform2fv(_location, value.Cell);
	}
}

void GLEffectProperty::SetVector3(const Math::Vector3& value) 
{
	if (_location != NoPosition)
	{
		GL::Uniform3fv(_location, value.Cell); 
	}
}

void GLEffectProperty::SetVector4(const Math::Vector4& value) 
{
	if (_location != NoPosition)
	{
		GL::Uniform4fv(_location, value.Cell); 
	}
}

void GLEffectProperty::SetMatrix3(const Math::Matrix3& value) 
{ 
	if (_location != NoPosition)
	{
		GL::UniformMatrix3f(_location, value.Cell);
	}
}

void GLEffectProperty::SetMatrix4(const Math::Matrix4& value) 
{ 
	if (_location != NoPosition)
	{
		GL::UniformMatrix4f(_location, value.Cell); 
	}
}
void GLEffectProperty::SetTexture2D(const ITexture2D* value) 
{
	GLenum unit = this->GetEffect()->As<GLEffect*>()->GetNextUnitID();
	GLenum textureUnit = GL_TEXTURE0 + unit;
	GL::ActiveTexture(textureUnit);

	GLuint handle = value->CastTo<const GLTexture2D*>()->GetTextureHandle();
	GL::BindTexture(GL_TEXTURE_2D, handle);
	SetInt32(unit);
}

} } } } }
